define(function(require, exports){
	var pubjs	= require('pubjs');
	var view	= require('@base/view');
	var util	= require('util');
	var $ = require('jquery');

	var Base = view.widget.extend({
		init:function(config){
			if(!config.get || !util.isFunc(config.get))
			{
				config = pubjs.conf(config);
			}

			var self = this;
			self.$isPop = config.get('isPop') || false;
			self.$isView = config.get('isView') || false;
			var vm = {
				'headTitle': config.get('Title') || ''
				,'isPop': self.$isPop
				,'isView': self.$isView
				,'isEdit':false
				,'isSave': false
				,'readonly': {}
				,'data': {}
			};
			var fields = config.get('fields');
			self.$fields = [];
			if(fields && fields.length) {
				self.$tips = {};
				util.each(fields, function(c) {
					self.$fields.push(c.field);
					switch (c.type)
					{
						case 'input':
						case 'textarea':
							vm[c.field] = c.defaultValue || '';
							c.width = c.width || 300;
							c.style = c.style || '';
							vm.readonly[c.field] = c.readonly || false;
							break;
						case 'radio':
							vm[c.field] = c.defaultValue || '';
							vm.data[c.field] = c.items || [];
							vm.readonly[c.field] = false;
							break;
						case 'bool':
							vm[c.field] = c.defaultValue || '';
							vm.data[c.field] = [{id: 1, name: 'True'}, {id: 0, name: 'False'}];
							vm.readonly[c.field] = false;
							break;
						case 'custom':
							c.style = c.style || '';
							break;
					}

					if(c.tip)
					{
						self.$tips[c.field + 'Tip'] = {
							'width': c.tipWidth || 300,
							'data': c.tip
						};
					}
				})
			}
			config = pubjs.conf(config, {
				isPopwin: false,
				module_name: '_view_',
				fields: [],
				view_model: vm,
				urlUpdate: '',
				urlAdd: '',
				urlInfo: ''
			});

			this.$id = null;
			this.Super('init', arguments);
		}
		,afterBuild:function(){
			var self = this;
			var c = self.getConfig();

			var body = $([
				`<div class="uk-form">
					<div class="M-formHead">
						<span class="M-formHeadTitle">{{headTitle}}</span>
					</div>
                    <div class="M-formCon">
                    </div>
                    <div  ms-visible="!isPop" class="M-formButtons">
                        <span pub-name="cancel" pub-mod="@base/common/input.button"></span>
                        <span pub-name="save" pub-mod="@base/common/input.button"></span>
                    </div>
                    <div  ms-class="dn: !isView" class="M-formButtons">
                        <span pub-name="back" pub-mod="@base/common/input.button"></span>
                    </div>
				</div>`
			].join(''));

			var config = {
				// 回退按钮
				'back': {
					'value': LANG('返回'),
					'class': 'btn btn-link'
				},
				// 表单取消按钮
				'cancel': {
					'value': LANG('取消'),
					'class': 'btn btn-link mr20'
				}
				// 表单保存按钮
				,'save': {
					'value': LANG('保存'),
					'class': 'btn btn-confirm'
				}
			};

			var con = body.find('.M-formCon');
			self.$field_doms = {};
			util.each(c.fields, function(c) {
				var t = self.$field_doms[c.field] = $(`
                        <div class="M-formConGroup">
                            <label class="group-label">${c.text += c.text ? LANG('：') : ''}</label>
                            <div class="group-content"></div>
                        </div>
				`);

				var content = t.find('.group-content');
				if(c.show_block)
				{
					content.removeClass('group-content').css({clear: 'both'});
				}
				if(c.parentCss)
				{
					content.css(c.parentCss);
				}
				if(c.divClass)
				{
					t.addClass(c.divClass);
				}
				switch (c.type) {
					case 'input':
						self.vm.watch(c.field, function(v, o) {
							self.dataChange(c.field, v, o);
						});

						content.append(`<input style="width: ${c.width}px" ms-disabled="readonly['${c.field}']"  ms-duplex="${c.field}" type="text" />`);
						break;
					case 'button':
						content.append(`<span pub-name="${c.field}" pub-mod="@base/common/input.button"></span>`);
						config[c.field] = c.config;
						break;
					case 'dropdown':
						content.append(`<span pub-name="${c.field}" pub-mod="@base/common/dropdown.${c.module || 'base'}"></span>`);
						config[c.field] = c.config;
						break;
					case 'custom':
						content.append(`<span style="${c.style}" pub-name="${c.field}" pub-mod="${c.uri}"></span>`);
						config[c.field] = c.config;
						break;
					case 'textarea':
						content.append(`
							<textarea style="${c.style}" ms-disabled="readonly['${c.field}']" ms-duplex="${c.field}" rows="${c.rows || 3}" class=""></textarea> `
						);
						break;
					case 'bool':
						self.vm.watch(c.field, function(v, o) {
							self.dataChange(c.field, v, o);
						});
						content.append(
						`<div ms-repeat-item="data['${c.field}']" class="fl mr5">
							<label class="cur_p" ms-attr-title="{{item.name}}">
								<input ms-disabled="readonly['${c.field}']" type="radio" ms-duplex-text="${c.field}" ms-value="item.id">
								<span>{{item.name}}</span>
							</label>
						</div>`);
						break;
					case 'radio':
						self.vm.watch(c.field, function(v, o) {
							self.dataChange(c.field, v, o);
						});
						content.append(
						`<div ms-repeat-item="data['${c.field}']" class="fl pr5">
							<label class="cur_p" ms-attr-title="{{item.name]}}">
								<input ms-disabled="readonly['${c.field}']" type="radio" ms-duplex-text="${c.field}" ms-value="item.id">
								<span>{{item.name}}</span>
							</label>
						</div>`);
				}

				if(c.tip) {
					content.append(`<span class="" pub-name="${c.field}Tip" pub-mod="@base/tip.desc"></span>`);
				}

				con.append(t);
			});
			var el = self.getContainer();
			el.append(body);
			$.extend(config, self.$tips || {});
			self.buildFromTemplate(config);
		}
		,afterBuildTemplate: function() {
			var self = this;
			var vm = self.vm;
		}
		,onDataChange: function(ev)
		{
			if(~this.$fields.indexOf(ev.name)) {
				this.dataChange(ev.name, ev.param);
			}
		}
		,onOptionChange: function(ev) {
			if(~this.$fields.indexOf(ev.name)) {
				this.dataChange(ev.name, ev.param.id);
			}
		}
		,onDropChange: function(ev)
		{
			if(~this.$fields.indexOf(ev.name)) {
				this.dataChange(ev.name, ev.param);
			}
		}
		,setTitle: function(v) {
			this.vm.$.headTitle = v;
			return this;
		}
		,dataChange: function(field, v) {
			this.fire('fieldChange', {value: v, field: field});
		}
		,toggle: function(field, state) {
			var self = this;
			if(field) {
				field = util.isArray(field) ? field : [field];
				util.each(field, function(f) {
					self.$field_doms[f].toggle(state);
				});
			}

			return this;
		}
		,enable: function(field) {
			return this.en_disable(field, true);
		}
		,disable: function(field) {
			return this.en_disable(field, false);
		}
		,en_disable: function(fields, state) {
			var self = this;
			if(!util.isArray(fields)) {
				fields = [fields];
			}

			util.each(fields, function(field) {
				if(self.$[field]) {
					if(state) {
						self.$[field].enable && self.$[field].enable();
					}
					else {
						self.$[field].disable && self.$[field].disable();
					}
				}
				else {
					var vm = self.vm.$;
					vm.readonly[field] = !state;
				}
			});

			return this;
		}
		,load: function(id){
			var self = this;
			self.$id = id;
			if(id){
				self.vm.$.isEdit = true;
				pubjs.loading.show();
				pubjs.mc.send(this.getConfig('urlInfo'), {_id: id}, function(err, data){
					pubjs.loading.hide();
					if(err){
						pubjs.alert(err.message);
						!self.$isPop && pubjs.controller.navigate(self.getConfig('nav') || -1);
						return false;
					}

					self.setData(data);
				})
			}

			return self;
		}
		,validate: function(data){
			var fields = this.getConfig('fields');
			var valid = true;
			var c;
			for(var i = 0; i < fields.length; i++) {
				c = fields[i];
				if(this.$field_doms[c.field].css('display') == 'none')
				{
					continue;
				}
				if(c.validate)
				{
					if(!data.hasOwnProperty(c.field) || data[c.field] === null || data[c.field] === undefined)
					{
						valid = false;
						pubjs.alert(LANG('请输入%1', c.text));
						break;
					}

					if(['input', 'textarea'].indexOf(c.type) > -1 && !data[c.field])
					{
						valid = false;
						pubjs.alert(LANG('请输入%1', c.text));
						break;
					}

					if(this.$[c.field] && this.$[c.field].validate)
					{
						if(!this.$[c.field].validate(data[c.field]))
						{
							valid = false;
							break;
						}
					}
				}
			}

			return valid;
		}
		,setData: function(data) {
			if(!data)
			{
				return this;
			}

			this.$data = data;
			var self = this
				,vm = self.vm.$;

			var fields = self.getConfig('fields');
			if(fields && fields.length) {
				util.each(fields, function(c) {
					switch(c.type) {
						case 'bool':
							vm[c.field] = data[c.field] ? 1 : 0;
							break;
						case 'input':
						case 'textarea':
						case 'radio':
							vm[c.field] = data.hasOwnProperty([c.field]) ? data[c.field] : '';
							break;
						case 'custom':
						case 'dropdown':
							var ch = self.$[c.field];
							var setValue = ch.setValue || ch.setData;
							setValue && setValue.call(ch, data[c.field]);
							self.dataChange(c.field, data[c.field]);
							break;
					}
				});
			}

			return self;
		}
		,set_field: function(field, value) {
			if(value) {
				var self = this
					,vm = self.vm.$;

				var fields = self.getConfig('fields');
				var c = util.find(fields, field, 'field');
				switch (c.type) {
					case 'bool':
						vm[c.field] = !!(+value);
						break;
					case 'input':
					case 'textarea':
					case 'radio':
						vm[c.field] = value;
						break;
					case 'custom':
					case 'dropdown':
						var ch = self.$[c.field];
						var setValue = ch.setValue || ch.setData;
						setValue && setValue.call(ch, value);
						self.dataChange(c.field, value);
						break;
				}
			}

			return this;
		}
		,getData: function(field){
			var self = this
				,c = self.getConfig()
				,data
				,fields = c.fields
				,ch
				,vm = self.vm.$;

			data = {
				_id: self.$id
			};

			if(fields && fields.length) {
				util.each(fields, function(c) {
					if(field && field !== c.field)
					{
						return;
					}

					if(self.$field_doms[c.field].css('display') == 'none') {
						return;
					}

					switch(c.type) {
						case 'input':
						case 'textarea':
						case 'radio':
						default :
							data[c.field] = vm[c.field];
							break;
						case 'bool':
							data[c.field] = !!(+vm[c.field]);
							break;
						case 'custom':
						case 'dropdown':
							ch = self.$[c.field];
							var getValue;
							if(c.getValue && util.isFunc(c.getValue))
							{
								getValue = c.getValue;
							}
							else
							{
								getValue = ch.getValue || ch.getData;
							}

							data[c.field] = getValue && getValue.call(ch);
							break;
					}
				});
			}

			return data;
		}
		,reset: function(){
			var self = this;
			this.$id = 0;
			this.toggle(this.$fields, true);
			this.vm.reset();
			var fields = self.getConfig('fields');
			if(fields && fields.length) {
				util.each(fields, function (c) {
					var ch = self.$[c.field];
					if(ch && ch.reset)
					{
						ch.reset();
					}
				});
			}

			this.en_disable(this.$fields, !this.vm.$.isView);
			return this;
		}
		,save: function(cb) {
			var self = this;
			var data = self.getData();
			var vm = self.vm.$;
			if(self.validate(data)) {
				pubjs.loading.show();
				var url = vm.isEdit ? 'urlUpdate' : 'urlAdd';
				pubjs.mc.send(self.getConfig(url), data, self.afterSave.bind(self), cb)
			}

			return false;
		}
		,afterSave: function(err, data, cb) {
			cb && cb(err, data);
			var self = this;
			pubjs.loading.hide();
			if(err) {
				pubjs.alert(err.message);
				return false;
			}

			var c = self.getConfig();
			if(c['isPopwin'])
			{
				self.hide();
			}
			else
			{
				!self.$isPop && pubjs.controller.navigate(self.getConfig('nav') || -1);
			}
		}
		,hide: function () {
			var c = this.getConfig();
			if(c['isPopwin'])
			{
				this.$[c.module_name].hide();
			}
			else
			{
				this.hide();
			}

			return this;
		}
		,onInputClick: function(ev) {
			var self = this;
			if(ev.name == 'save') {
				this.save();
			}
			else if(ev.name == 'cancel') {
				if(this.getConfig('isPopwin'))
				{
					self.hide();
				}
				else
				{
					!self.$isPop && pubjs.controller.navigate(self.getConfig('nav') || -1);
				}
			}
			else if(ev.name == 'back')
			{
				pubjs.controller.navigate(self.getConfig('nav') || -1);
			}
			else
			{
				self.dataChange(ev.name);
			}

			return false;
		}
	});

	exports.base = Base;
});